class ChunkUploader {
    constructor(options) {
        this.baseUrl = options.baseUrl || '/admin/product/chunk';
        this.chunkSize = options.chunkSize || 2 * 1024 * 1024; // 2MB
        this.maxRetries = options.maxRetries || 3;
        this.onProgress = options.onProgress || (() => {});
        this.onComplete = options.onComplete || (() => {});
        this.onError = options.onError || (() => {});
    }

    // 计算文件hash作为唯一标识符
    async calculateFileHash(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = async (e) => {
                const buffer = e.target.result;
                const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
                const hashArray = Array.from(new Uint8Array(hashBuffer));
                const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
                resolve(hashHex);
            };
            reader.onerror = reject;
            reader.readAsArrayBuffer(file);
        });
    }

    // 检查文件是否已存在（秒传）
    async checkFileExists(fileIdentifier, fileName) {
        try {
            const response = await fetch(
                `${this.baseUrl}/check/${fileIdentifier}?fileName=${encodeURIComponent(fileName)}`
            );
            const result = await response.json();
            return result.data;
        } catch (error) {
            console.error('检查文件失败:', error);
            return null;
        }
    }

    // 检查上传状态
    async checkUploadStatus(fileIdentifier) {
        try {
            const response = await fetch(`${this.baseUrl}/status/${fileIdentifier}`);
            const result = await response.json();
            return result.data;
        } catch (error) {
            console.error('检查状态失败:', error);
            return null;
        }
    }

    // 上传分片
    async uploadChunk(chunk, chunkIndex, fileInfo, retryCount = 0) {
        const formData = new FormData();
        formData.append('chunk', chunk);
        formData.append('fileIdentifier', fileInfo.fileIdentifier);
        formData.append('fileName', fileInfo.fileName);
        formData.append('totalSize', fileInfo.totalSize);
        formData.append('chunkSize', this.chunkSize);
        formData.append('totalChunks', fileInfo.totalChunks);
        formData.append('chunkIndex', chunkIndex);
        formData.append('currentChunkSize', chunk.size);
        formData.append('contentType', fileInfo.contentType);

        try {
            const response = await fetch(`${this.baseUrl}/upload`, {
                method: 'POST',
                body: formData
            });

            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }

            const result = await response.json();
            return result.data;
        } catch (error) {
            if (retryCount < this.maxRetries) {
                console.warn(`分片 ${chunkIndex} 上传失败，重试第 ${retryCount + 1} 次:`, error);
                await new Promise(resolve => setTimeout(resolve, 1000 * (retryCount + 1))); // 指数退避
                return this.uploadChunk(chunk, chunkIndex, fileInfo, retryCount + 1);
            }
            throw error;
        }
    }

    // 合并分片
    async mergeChunks(fileInfo) {
        try {
            const response = await fetch(`${this.baseUrl}/merge`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    fileIdentifier: fileInfo.fileIdentifier,
                    fileName: fileInfo.fileName,
                    totalSize: fileInfo.totalSize,
                    totalChunks: fileInfo.totalChunks,
                    contentType: fileInfo.contentType
                })
            });

            const result = await response.json();
            return result.data;
        } catch (error) {
            console.error('合并分片失败:', error);
            throw error;
        }
    }

    // 主上传方法
    async upload(file) {
        try {
            // 1. 计算文件hash
            const fileIdentifier = await this.calculateFileHash(file);
            const fileName = file.name;
            const totalSize = file.size;
            const totalChunks = Math.ceil(totalSize / this.chunkSize);
            const contentType = file.type;

            const fileInfo = {
                fileIdentifier,
                fileName,
                totalSize,
                totalChunks,
                contentType
            };

            // 2. 检查文件是否已存在（秒传）
            const existingFile = await this.checkFileExists(fileIdentifier, fileName);
            if (existingFile) {
                this.onComplete(existingFile);
                return existingFile;
            }

            // 3. 检查断点续传状态
            const uploadStatus = await this.checkUploadStatus(fileIdentifier);
            const uploadedChunks = uploadStatus ? uploadStatus.uploadedChunks : [];

            // 4. 分片上传
            const promises = [];
            for (let i = 0; i < totalChunks; i++) {
                if (uploadedChunks.includes(i)) {
                    continue; // 跳过已上传的分片
                }

                const start = i * this.chunkSize;
                const end = Math.min(start + this.chunkSize, totalSize);
                const chunk = file.slice(start, end);

                promises.push(
                    this.uploadChunk(chunk, i, fileInfo).then(result => {
                        this.onProgress({
                            progress: result.progress,
                            chunkIndex: i,
                            totalChunks: totalChunks
                        });
                        return result;
                    })
                );
            }

            // 5. 等待所有分片上传完成
            await Promise.all(promises);

            // 6. 合并分片
            const finalResult = await this.mergeChunks(fileInfo);
            this.onComplete(finalResult);
            return finalResult;

        } catch (error) {
            this.onError(error);
            throw error;
        }
    }
}

// 使用示例
const uploader = new ChunkUploader({
    baseUrl: '/admin/product/chunk',
    chunkSize: 2 * 1024 * 1024, // 2MB
    onProgress: (data) => {
        console.log(`上传进度: ${data.progress.toFixed(2)}%`);
    },
    onComplete: (fileInfo) => {
        console.log('上传完成:', fileInfo);
    },
    onError: (error) => {
        console.error('上传失败:', error);
    }
});

// 监听文件选择
document.getElementById('fileInput').addEventListener('change', async (e) => {
    const file = e.target.files[0];
    if (file) {
        try {
            await uploader.upload(file);
        } catch (error) {
            console.error('文件上传失败:', error);
        }
    }
});